package me.luger.project.fof.service;

import me.luger.core.commom.util.DateUtil;
import me.luger.core.commom.util.LogUtil;
import me.luger.core.commom.util.StringUtil;
import me.luger.core.dao.nutz.entity.page.Pagination;
import me.luger.core.dao.nutz.service.BaseService;
import me.luger.project.fof.config.cache.redis.RedisManager;
import me.luger.project.fof.entity.AssetStrategyInfo;
import me.luger.project.fof.entity.FundInfo;
import me.luger.project.fof.entity.FundInfoFilterConfig;
import me.luger.project.fof.entity.ProductType;
import org.apache.commons.collections.map.HashedMap;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;

import java.util.*;

@Repository
public class FundInfoService extends BaseService<FundInfo> {

    @Autowired
    private ProductTypeService productTypeService;

    @Autowired
    private FundCollectService fundCollectService;

    @Autowired
    private AssetStrategyInfoService assetStrategyInfoService;

    @Autowired
    private RedisManager redisManager;

    public FundInfoService(Dao dao) {
        super(dao);
    }
//
//    @Cacheable(value = "short_time_cache")
//    public Pagination filterFundInfoByProductType1(Integer productTypeId, Integer fundType, Integer curAssetStrategyId, String key,
//                                                  String sortType,
//                                                  String sortName,
//                                                  int all,
//                                                  int pageNumber, int pageSize) {
//        ProductType productType = productTypeService.fetchById(productTypeId);
//
//        String assetStrategyIds = productType.getAssetStrategyIds();
//        if (StringUtil.isBlank(assetStrategyIds)) {
//            return null;
//        }
//
//        String fundTypeTarget = "";
//        String fundTypeStrategy = "";
//        String fundTypeQuant = "";
//        String fundTypeHedging = "";
//
//        List<Map> allKindAssetStrategy = new ArrayList<Map>();
//
//        for (String assetStrategyId : assetStrategyIds.split(",")) {
//            if (StringUtil.isBlank(assetStrategyId)) continue;
//
//            AssetStrategyInfo assetStrategyInfo = assetStrategyInfoService.fetchById(Long.valueOf(assetStrategyId));
//            fundTypeTarget += assetStrategyInfo.getGoFundTypeTarget() + "," + assetStrategyInfo.getWindInvestType() + ",";
//            fundTypeStrategy += assetStrategyInfo.getGoFundTypeStrategy() + ",";
//            fundTypeQuant += assetStrategyInfo.getGoFundTypeQuant() + ",";
//            fundTypeHedging += assetStrategyInfo.getGoFundTypeHedging() + ",";
//
//            Map<String, Object> assetStrategyMap = new HashedMap();
//            assetStrategyMap.put("assetStrategyId", assetStrategyId);
//            assetStrategyMap.put("assetStrategName", assetStrategyInfo.getName());
//            allKindAssetStrategy.add(assetStrategyMap);
//        }
//
//        if (0 != curAssetStrategyId) {//如果传入的资产策略类型不为空则只取资产策略类型下的基金数据
//            AssetStrategyInfo assetStrategyInfo = assetStrategyInfoService.fetchById(Long.valueOf(curAssetStrategyId));
//            fundTypeTarget = assetStrategyInfo.getGoFundTypeTarget() + "," + assetStrategyInfo.getWindInvestType() + ",";
//            fundTypeStrategy = assetStrategyInfo.getGoFundTypeStrategy() + ",";
//            fundTypeQuant = assetStrategyInfo.getGoFundTypeQuant() + ",";
//            fundTypeHedging = assetStrategyInfo.getGoFundTypeHedging() + ",";
//        }
//
//
//        String[] fundTypeTargetArr = new String[]{};
//        String[] fundTypeStrategyArr = new String[]{};
//        String[] fundTypeQuantArr = new String[]{};
//        String[] fundTypeHedgingArr = new String[]{};
//
//        if (StringUtil.isNotBlank(fundTypeTarget)) {
//            fundTypeTargetArr = fundTypeTarget.split(",");
//        }
//        if (StringUtil.isNotBlank(fundTypeStrategy)) {
//            fundTypeStrategyArr = fundTypeStrategy.split(",");
//        }
//        if (StringUtil.isNotBlank(fundTypeQuant)) {
//            fundTypeQuantArr = fundTypeQuant.split(",");
//        }
//        if (StringUtil.isNotBlank(fundTypeHedging)) {
//            fundTypeHedgingArr = fundTypeHedging.split(",");
//        }
//
//
//        StringBuilder nativeSql = new StringBuilder("select * from fund_info where 1=1 and fund_status = 1");// and filter_status = 1
//
//        if (all == 0) {
//            nativeSql.append(" and filter_status = 1 ");
//        }
//
//        //1表示万得(公募)，2表示朝阳永续(私募) 0 全部
//        if (fundType == 1 || fundType == 2) {
//            nativeSql.append(" and fund_ext_source = " + fundType);
//        }
//
//        if (StringUtil.isNotBlank(key)) {
//            nativeSql.append(" and (");
//            String[] keyArr = key.split(" ");
//            for (int i = 0; i < keyArr.length; i++) {
//                nativeSql.append(" fund_name_full like @key" + i + " or");
//            }
//            if (nativeSql.toString().endsWith("or")) {
//                nativeSql = new StringBuilder(nativeSql.subSequence(0, nativeSql.length() - 2));
//            }
//            nativeSql.append(" )");
//        }
//
//        nativeSql.append(" and");
//
//
//        nativeSql.append(" (");
//
//        for (String item : fundTypeTargetArr) {
//            nativeSql.append(" fund_type_target like '%" + item + "%' or");
//        }
//
//        for (String item : fundTypeStrategyArr) {
//            nativeSql.append(" fund_type_strategy like '%" + item + "%' or");
//        }
//        for (String item : fundTypeQuantArr) {//这个用精确匹配
//            nativeSql.append(" fund_type_quant = '" + item + "' or");
//        }
//        for (String item : fundTypeHedgingArr) {//这个用精确匹配
//            nativeSql.append(" fund_type_hedging = '" + item + "' or");
//        }
//
//        if (nativeSql.toString().endsWith("or")) {
//            nativeSql = new StringBuilder(nativeSql.subSequence(0, nativeSql.length() - 2));
//        }
//
//        nativeSql.append(")");
//
//        if (StringUtil.isNotBlank(sortName) && StringUtil.isNotBlank(sortType)) {
//            nativeSql.append(" order by ").append(sortName + " ").append(sortType);
//        }
//
//        LogUtil.infoLog("fundFilter slq = " + nativeSql.toString());
//
//        Sql filterFundInfoSql = Sqls.create(nativeSql.toString());
//
//
//        if (StringUtil.isNotBlank(key)) {
//            String[] keyArr = key.split(" ");
//            for (int i = 0; i < keyArr.length; i++) {
//                String keyItem = keyArr[i];
//                filterFundInfoSql.setParam("key" + i, "%" + keyItem + "%");
//            }
//        }
//
//
//        Pagination filterdFundInfo = this.listPage(pageNumber, pageSize, filterFundInfoSql);
//
////        Set<String> allKindFundTarget = getAllKindFundTarget(fundType,fundTypeTargetArr,fundTypeStrategyArr,fundTypeQuantArr,fundTypeHedgingArr);
//
//        filterdFundInfo.addExt("allKindAssetStrategy", allKindAssetStrategy);
//        filterdFundInfo.addExt("curAssetStrategyId", curAssetStrategyId);
//        filterdFundInfo.addExt("key", key);
//
//        return filterdFundInfo;
//    }


    @Cacheable(value = "short_time_cache")
    public Pagination filterFundInfoByProductType(Integer productTypeId, Integer fundType, Integer curAssetStrategyId, String key,
                                                  String sortType,
                                                  String sortName,
                                                  int all,
                                                  String manager,
                                                  String management,Integer uid,
                                                  int pageNumber, int pageSize) {
        ProductType productType = productTypeService.fetchById(productTypeId);

        String assetStrategyIds = productType.getAssetStrategyIds();
        if (StringUtil.isBlank(assetStrategyIds)) {
            return null;
        }
        if(assetStrategyIds.startsWith(",")){
            assetStrategyIds = assetStrategyIds.substring(1);
        }
        if(assetStrategyIds.endsWith(",")){
            assetStrategyIds = assetStrategyIds.substring(0,assetStrategyIds.length()-1);
        }

        List<Map> allKindAssetStrategy = new ArrayList<Map>();

        for (String assetStrategyId : assetStrategyIds.split(",")) {
            if (StringUtil.isBlank(assetStrategyId)){
                continue;
            }

            AssetStrategyInfo assetStrategyInfo = assetStrategyInfoService.fetchById(Long.valueOf(assetStrategyId));

            Map<String, Object> assetStrategyMap = new HashedMap();
            assetStrategyMap.put("assetStrategyId", assetStrategyId);
            assetStrategyMap.put("assetStrategName", assetStrategyInfo.getName());
            allKindAssetStrategy.add(assetStrategyMap);
        }

        String field = "";
        if (0 != curAssetStrategyId) {//如果传入的资产策略类型不为空则只取资产策略类型下的基金数据
            field = "a.*,b.assetStrategyId";
        }else{
            field = "distinct a.*";//去重
        }
        StringBuilder nativeSql = new StringBuilder("select "+field+" from fund_info a left join fof_fund_asset_strategy b on a.fund_ext_code = b.fund_ext_code where 1=1 and fund_status = 1");// and filter_status = 1

        if (all == 0) {
            nativeSql.append(" and filter_status = 1 ");
        }

        //1表示万得(公募)，2表示朝阳永续(私募) 0 全部
        if (fundType == 1 || fundType == 2) {
            nativeSql.append(" and fund_ext_source = " + fundType);
        }

        if(StringUtil.isNotBlank(key)){
            if(key.contains("&")){
                nativeSql.append(" and (");
                String[] keyArr = key.split("&");
                for (int i = 0; i < keyArr.length; i++) {
                    nativeSql.append(" searchKey like @key" + i + " and");
                }
                if (nativeSql.toString().endsWith("and")) {
                    nativeSql = new StringBuilder(nativeSql.subSequence(0, nativeSql.length() - 3));
                }
                nativeSql.append(" )");
            }else if(key.contains(" ")){
                nativeSql.append(" and (");
                String[] keyArr = key.split(" ");
                for (int i = 0; i < keyArr.length; i++) {
                    nativeSql.append(" searchKey like @key" + i + " or");
                }
                if (nativeSql.toString().endsWith("or")) {
                    nativeSql = new StringBuilder(nativeSql.subSequence(0, nativeSql.length() - 2));
                }
                nativeSql.append(" )");
            }else{
                nativeSql.append(" and searchKey like @key0");
            }
        }

        if(StringUtil.isNotBlank(manager)){
            nativeSql.append(" and fund_manager = @manager");
        }

        if(StringUtil.isNotBlank(management)){
            nativeSql.append(" and fund_management_company = @management");
        }



        if (0 != curAssetStrategyId) {//如果传入的资产策略类型不为空则只取资产策略类型下的基金数据
            nativeSql.append(" and assetStrategyId = " + curAssetStrategyId);
        }else{
            nativeSql.append(" and assetStrategyId in (" + assetStrategyIds + ")");
        }

        if (StringUtil.isNotBlank(sortName) && StringUtil.isNotBlank(sortType)) {
            nativeSql.append(" order by ").append(sortName + " ").append(sortType);
        }



        Sql filterFundInfoSql = Sqls.create(nativeSql.toString());


        if (StringUtil.isNotBlank(key)) {
            String[] keyArr  = new String[]{key};
            if(key.contains("&")){
                keyArr = key.split("&");
            }else if(key.contains(" ")){
                keyArr = key.split(" ");
            }

            for (int i = 0; i < keyArr.length; i++) {
                String keyItem = keyArr[i];
                filterFundInfoSql.setParam("key" + i, "%" + keyItem + "%");
            }
        }

        if(StringUtil.isNotBlank(manager)){
            filterFundInfoSql.setParam("manager",manager);
        }

        if(StringUtil.isNotBlank(management)){
            filterFundInfoSql.setParam("management",management);
        }

        LogUtil.infoLog("fundFilter slq = " + filterFundInfoSql.toString());
        Pagination filterdFundInfo = this.listPage(pageNumber, pageSize, filterFundInfoSql);

//        Set<String> allKindFundTarget = getAllKindFundTarget(fundType,fundTypeTargetArr,fundTypeStrategyArr,fundTypeQuantArr,fundTypeHedgingArr);

        filterdFundInfo.addExt("allKindAssetStrategy", allKindAssetStrategy);
        filterdFundInfo.addExt("curAssetStrategyId", curAssetStrategyId);
        filterdFundInfo.addExt("key", key);

        return filterdFundInfo;
    }

    public Pagination<FundInfo> myCollect(Integer uid,Integer pn,Integer rn) {
        long start = (pn-1) * rn;
        long end = start + rn - 1;
        String redisKey = "fof:user:fund:collect:"+uid;
        Set<String> extCodeSet = redisManager.zrange(redisKey,start,end);
        if(null == extCodeSet || extCodeSet.size() == 0){
            return null;
        }

        StringBuffer sbSql = new StringBuffer("select * from fund_info a where 1=1 and a.fund_status = 1 and (");

        for(String extCode : extCodeSet){
            sbSql.append("fund_ext_code = '" + extCode + "' or ");
        }

        String sbSqlStr = sbSql.toString();
        if(sbSqlStr.endsWith("or ")){
            sbSqlStr = sbSqlStr.substring(0,sbSqlStr.length()-3);
        }
        sbSqlStr+=")";

        System.out.printf("luger sql = "+sbSqlStr);
        Sql sql = Sqls.create(sbSqlStr);
        Pagination<FundInfo> fundInfo = this.listPage(pn,rn,sql);
        return fundInfo;
    }

    @Cacheable(value = "long_time_cache")
    public Set<String> getAllKindFundTarget(Integer fundType, String[] fundTypeTargetArr, String[] fundTypeStrategyArr, String[] fundTypeQuantArr, String[] fundTypeHedgingArr) {
        StringBuilder nativeSql = new StringBuilder("select distinct fund_type_target from fund_info where 1=1");
        if (fundType == 1 || fundType == 0) {
            nativeSql.append(" and fund_ext_source = " + fundType);
        }
        nativeSql.append(" and");

        nativeSql.append(" (");

        for (String item : fundTypeTargetArr) {
            nativeSql.append(" fund_type_target like '%" + item + "%' or");
        }

        for (String item : fundTypeStrategyArr) {
            nativeSql.append(" fund_type_strategy like '%" + item + "%' or");
        }
        for (String item : fundTypeQuantArr) {
            nativeSql.append(" fund_type_quant like '%" + item + "%' or");
        }
        for (String item : fundTypeHedgingArr) {
            nativeSql.append(" fund_type_hedging like '%" + item + "%' or");
        }

        if (nativeSql.toString().endsWith("or")) {
            nativeSql = new StringBuilder(nativeSql.subSequence(0, nativeSql.length() - 2));
        }

        nativeSql.append(")");

        Sql allKindFundTargetSql = Sqls.create(nativeSql.toString());

        List<FundInfo> allKindFundTargetFundInfo = this.list(allKindFundTargetSql);

        Set<String> allKindFundTargetList = new HashSet<String>();
        for (FundInfo fundInfo : allKindFundTargetFundInfo) {
            String fundTypeTarget = fundInfo.getFundTypeTarget();
            if (StringUtil.isBlank(fundTypeTarget)) {
                continue;
            }
            allKindFundTargetList.addAll(Arrays.asList(fundTypeTarget.split(",")));
        }
        return allKindFundTargetList;
    }

    /**
     * 根据管理平台配置的筛选条件进行基金筛选
     *
     * @param fundInfoFilterConfig
     * @return 1：筛选成功
     * -1：筛选失败
     */
    public int filterFundInfo(FundInfoFilterConfig fundInfoFilterConfig) {
        try {
            this.execute(Sqls.create("update fund_info set filter_status_temp = 0"));


            StringBuilder updateSqlBuilder = new StringBuilder("update fund_info set filter_status = 1,filter_status_temp = 1 where 1 = 1 ");
            if (fundInfoFilterConfig.getYieldAnnuallyUp() != null) {
                updateSqlBuilder.append(" and yieldAnnually <=" + fundInfoFilterConfig.getYieldAnnuallyUp());
            }
            if (fundInfoFilterConfig.getYieldAnnuallyDown() != null) {
                updateSqlBuilder.append(" and yieldAnnually >=" + fundInfoFilterConfig.getYieldAnnuallyDown());
            }

            if (fundInfoFilterConfig.getDrawdownUp() != null) {
                updateSqlBuilder.append(" and drawdown <=" + fundInfoFilterConfig.getDrawdownUp());
            }
            if (fundInfoFilterConfig.getDrawdownDown() != null) {
                updateSqlBuilder.append(" and drawdown >=" + fundInfoFilterConfig.getDrawdownDown());
            }

            if (fundInfoFilterConfig.getVolatilityAnnuallyUp() != null) {
                updateSqlBuilder.append("and volatilityAnnually <=" + fundInfoFilterConfig.getVolatilityAnnuallyUp());
            }
            if (fundInfoFilterConfig.getVolatilityAnnuallyDown() != null) {
                updateSqlBuilder.append("and volatilityAnnually >=" + fundInfoFilterConfig.getVolatilityAnnuallyDown());
            }

            if (fundInfoFilterConfig.getYield1yUp() != null) {
                updateSqlBuilder.append(" and yield1y <=" + fundInfoFilterConfig.getYield1yUp());
            }
            if (fundInfoFilterConfig.getYield1yDown() != null) {
                updateSqlBuilder.append(" and yield1y >=" + fundInfoFilterConfig.getYield1yDown());
            }

            if (fundInfoFilterConfig.getYield3yUp() != null) {
                updateSqlBuilder.append(" and yield3y <=" + fundInfoFilterConfig.getYield3yUp());
            }
            if (fundInfoFilterConfig.getYield3yDown() != null) {
                updateSqlBuilder.append(" and yield3y >=" + fundInfoFilterConfig.getYield3yDown());
            }

            if (fundInfoFilterConfig.getYield5yUp() != null) {
                updateSqlBuilder.append(" and yield5y <=" + fundInfoFilterConfig.getYield5yUp());
            }
            if (fundInfoFilterConfig.getYield5yDown() != null) {
                updateSqlBuilder.append(" and yield5y >=" + fundInfoFilterConfig.getYield5yDown());
            }

            if (fundInfoFilterConfig.getSharpRatioUp() != null) {
                updateSqlBuilder.append(" and sharpRatio <=" + fundInfoFilterConfig.getSharpRatioUp());
            }
            if (fundInfoFilterConfig.getSharpRatioDown() != null) {
                updateSqlBuilder.append(" and sharpRatio >=" + fundInfoFilterConfig.getSharpRatioDown());
            }

            if (fundInfoFilterConfig.getNoDavYears() != null && 0 != fundInfoFilterConfig.getNoDavYears()) {
                Date lastUpdateDate = DateUtil.add(DateUtil.nowAsDate(), -fundInfoFilterConfig.getNoDavYears() * 365 * 24 * 60 * 60);
                updateSqlBuilder.append(" and lastUpdateDate >= '" + DateUtil.format(lastUpdateDate, DateUtil.DATE_TIME_YYYY_MM_DD_HH_MM_SS) + "'");
            }

            if (StringUtil.isNotBlank(fundInfoFilterConfig.getNavStartDate())) {
                updateSqlBuilder.append(" and fund_fundation_date >= '" + fundInfoFilterConfig.getNavStartDate() + "'");
            }

            if (StringUtil.isNotBlank(fundInfoFilterConfig.getNavEndate())) {
                updateSqlBuilder.append(" and lastUpdateDate >= '" + fundInfoFilterConfig.getNavEndate() + "'");
            }

            if (null != fundInfoFilterConfig.getNavMinDot() && fundInfoFilterConfig.getNavMinDot() > 0) {
                updateSqlBuilder.append(" and navDotcount >= " + fundInfoFilterConfig.getNavMinDot());
            }

            Sql updateSql = Sqls.create(updateSqlBuilder.toString());

            updateSql = this.execute(updateSql);

            this.execute(Sqls.create("update fund_info set filter_status = 0 where filter_status_temp = 0"));

            fundInfoFilterConfig.setUpdateTime(DateUtil.nowAsDate());
            this.update(fundInfoFilterConfig);
        } catch (Exception e) {
            LogUtil.errorLog(e, "filterFundInfo error");
            return -1;
        }
        return 1;


    }

    public List<FundInfo> getFundsInfo(String[] fundIds){
        String selectSql = "select * from fund_info where fund_ext_code in (";
        for(String fundId : fundIds){
            selectSql += "'"+fundId+"',";
        }
        selectSql = selectSql.substring(0,selectSql.length()-1);
        selectSql += ")";
        Sql sql = Sqls.create(selectSql);
        List<FundInfo> fundInfoList = this.list(sql);
        return fundInfoList;
    }

    public Pagination<FundInfo> getFundsInfoByManager(String manager,Integer pn,Integer rn){
        String selectSql = "select * from fund_info where fund_manager = @manager";
        Sql sql = Sqls.create(selectSql);
        sql.setParam("manager",manager);
        Pagination<FundInfo> fundInfoList = this.listPage(pn,rn,sql);
        return fundInfoList;
    }

    public Pagination<FundInfo> getFundsInfoByManagement(String management,Integer pn,Integer rn){
        String selectSql = "select * from fund_info where fund_management_company = @management";
        Sql sql = Sqls.create(selectSql);
        sql.setParam("management",management);
        Pagination<FundInfo> fundInfoList = this.listPage(pn,rn,sql);
        return fundInfoList;
    }

    /**
     * 获取FUND的基本信息
     *
     * @param fundExtCode
     * @return
     */
    public FundInfo getFundInfo(String fundExtCode) {
        Sql sql = Sqls.create("select * from `fund_info` fundInfo " +
                "where fundInfo.`fund_ext_code` = @fundExtCode");
        sql.params().set("fundExtCode", fundExtCode);
        List<FundInfo> fundInfoList = this.list(sql);
        if (fundInfoList != null && fundInfoList.size() > 0) {
            return fundInfoList.get(0);
        }
        return null;
    }

    public void updateCollectStatus(Pagination fundPageList,Integer uid) {
        List<FundInfo> fundInfoList = fundPageList.getList();
        for(FundInfo fundInfo : fundInfoList){
            boolean isCollect = fundCollectService.isCollect(uid,fundInfo.getFundExtCode());
            fundInfo.setCollect(isCollect);
        }
        fundPageList.setList(fundInfoList);
    }
}
